<?php

declare(strict_types=1);

namespace App\Model;

use App\Constants\InviteVideoCode;
use App\Helpers\ConfigUtil;
use App\Helpers\DateUtil;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\DbConnection\Db;
use Hyperf\DbConnection\Model\Model;

/**
 *  通话基类模型
 */
class CallBase extends Model
{
    //类型
    const CALL_TYPE = -1;

    //正在呼叫
    const STATUS_NO_PICK = 0;
    //正在通话
    const STATUS_ING = 1;
    //已接听-正常挂断
    const STATUS_OK = 2;
    //已接听-异常挂断
    const STATUS_ERR_HANGUP = 3;
    //已接听-运营后台关闭
    const STATUS_ADMIN_HANGUP = 4;
    //已接听-涉黄挂断
    const STATUS_YELLOW_HANGUP = 7;
    //未接通-呼叫方挂
    const STATUS_CALLER_STOP = 5;
    //未接通-被叫方拒
    const STATUS_HOST_REJECT = 6;
    //未接通-已失效（无人接听）
    const STATUS_INVALID = -1;
    const STATUS = [
        self::STATUS_NO_PICK => '正在呼叫',
        self::STATUS_ING => '已接听-正在通话',
        self::STATUS_OK => '已接听-正常挂断',
        self::STATUS_ERR_HANGUP => '已接听-异常挂断',
        self::STATUS_ADMIN_HANGUP => '已接听-运营后台关闭',
        self::STATUS_YELLOW_HANGUP => '已接听-涉黄挂断',
        self::STATUS_INVALID => '未接通-已失效（无人接听及其他）',
        self::STATUS_CALLER_STOP => '未接通-呼叫挂',
        self::STATUS_HOST_REJECT => '未接通-被叫拒'
    ];

    //来源-新手福利
    const FROM_NEW = 1;
    //来源-一键聊天
    const FROM_QUCIK = 2;
    //来源-首页主播
    const FROM_MAIN = 3;
    //随心聊
    const FROM_QUICK_MESSAGE = 4;
    //天天福利
    const FROM_DAILY_FREE = 5;
    //IOS匹配
    const FROM_IOS_QUICK_MATCH = 6;
    //天天福利-主播
    const FROM_DAILY_FREE_HOST = 7;
    //主播呼叫
    const FROM_HOST_CALL = 8;

    //视频邀约呼叫
    const FROM_INVITE_CALL = 9;

    // 特惠视频
    const FROM_DISCOUNT_CALL = 10;

    //成功通话的状态
    const DONE_STATUS = [self::STATUS_OK, self::STATUS_ERR_HANGUP, self::STATUS_ADMIN_HANGUP];
    //异常挂断
    const ERR_STATUS = [self::STATUS_ERR_HANGUP, self::STATUS_ADMIN_HANGUP];
    //失败的状态
    const FAIL_STATUS = [self::STATUS_INVALID, self::STATUS_CALLER_STOP, self::STATUS_HOST_REJECT];

    /**
     * 获取记录
     */
    static function getCall($callId = 0)
    {
        return self::find($callId);
    }

    /**
     * 根据声网频道ID获取记录
     */
    static function getInfoByChannel($channelId = 0)
    {
        return self::where('channel_id', $channelId)->first();
    }

    /**
     * 更新信息
     */
    static function updateInfo($recordId = 0, $info = [])
    {
        if (!$recordId || empty($info)) return false;
        return self::where('id', $recordId)->limit(1)->update($info);
    }

    /**
     * 获取用户的通话记录
     * @Cacheable(prefix="call_list", ttl=300, value="_#{userId}", listener="call_list_update")
     */
    static function getUserLogs($userId = 0, $page = 1)
    {
        log_info(__METHOD__ . "=={$userId}");
        $where = ['user_id' => $userId];
        $orWhere = ['chat_user_id' => $userId];
        $pageNum = 100;
        $start = ($page - 1) * $pageNum;
        // $items = Db::table('video_call')->where($where)->whereIn('status', self::DONE_STATUS)->orWhere(function ($query) use ($orWhere) {
        //     $query->where($orWhere)->whereIn('status', self::DONE_STATUS);
        // })->orderBy('id', 'desc')->offset($start)->limit($pageNum)->get();
        $items = array_merge(
            VideoCall::where($where)->whereIn('status', self::DONE_STATUS)->orderBy('id', 'desc')->offset($start)->limit($pageNum)->get()->toArray(),
            VideoCall::where($orWhere)->whereIn('status', self::DONE_STATUS)->orderBy('id', 'desc')->offset($start)->limit($pageNum)->get()->toArray()
        );
        array_multisort(array_column($items, 'id'), SORT_DESC, $items);
        $list = [];
        foreach ($items as $item) {
            if ($item['from'] == CallBase::FROM_HOST_CALL) $caller = $item['user_id'] == $userId ? 0 : 1;
            else $caller = $item['user_id'] == $userId ? 1 : 0;
            $list[] = [
                'chat_user_id' => $item['user_id'] == $userId ? $item['chat_user_id'] : $item['user_id'],
                'duration' => $item['call_time'],
                'start_time' => $item['start_time'],
                'status' => $item['status'],
                'is_caller' => $caller,
                'channel_id' => $item['channel_id'],
                'call_id' => $item['id'],
                'call_type' => $item['call_type'],
                'from' => $item['from'],
                'call_mark' => $item['call_mark'],
            ];
        }
        return $list;
    }

    /**
     * 添加记录
     */
    static function addRecord(
        $userId = 0,
        $chatUserId = 0,
        $from = self::FROM_MAIN,
        $coinSetting = 0.0,
        $callMark = 1
    ) {
        return self::create([
            'user_id' => $userId,
            'chat_user_id' => $chatUserId,
            'start_time' => time(),
            'status' => self::STATUS_NO_PICK,
            'from' => $from,
            'coin_setting' => $coinSetting,
            'call_mark' => $callMark
        ]);
    }

    /**
     * 强行结束用户之前的语聊记录
     */
    static function finishOldCall($userId = 0)
    {
        $invalidStatus = [self::STATUS_NO_PICK]; //self::STATUS_ING
        return self::where('user_id', $userId)->whereIn('status', $invalidStatus)->update([
            'status' => self::STATUS_INVALID,
            'end_time' => time(),
        ]);
    }

    /**
     * 查找双方的语聊记录
     */
    static function checkRecord($userId = 0, $chatUserId = 0, $channelId = '')
    {
        $where = [
            'user_id' => $userId,
            'chat_user_id' => $chatUserId
        ];
        $orWhere = [
            'user_id' => $chatUserId,
            'chat_user_id' => $userId,
        ];
        if ($channelId) $where['channel_id'] = $orWhere['channel_id'] = $channelId;
        return self::where($where)->orWhere(function ($query) use ($orWhere) {
            $query->where($orWhere);
        })->orderBy('id', 'desc')->first();
    }

    /**
     * 获取用户最后一条拨打记录
     */
    static function checkLastRecord($userId = 0)
    {
	    
        $where = ['user_id' => $userId];
        $orWhere = ['chat_user_id' => $userId];
        return self::where($where)->orWhere(function ($query) use ($orWhere) {
            $query->where($orWhere);
        })->orderBy('id', 'desc')->first();
    }

    /**
     * 回调处理-进入频道
     */
    static function callbackChannelIn($userId = 0, $chatUserId = 0, $channelId = '', $channelInUserId = 0)
    {
        if ($userId == $chatUserId || !$userId || !$chatUserId || !$channelId) return false;
        $log = self::checkRecord($userId, $chatUserId);
        if (!$log || $log->status != self::STATUS_NO_PICK) return false;
        //更新频道ID
        $log->channel_id = $channelId;
        //接听方进入频道，已接通，通话开始
        if ($channelInUserId == $chatUserId) {
            $log->status = self::STATUS_ING;
            $log->answer_time = $log->heartbeat_user = $log->heartbeat_chat = time();
            //使用免费福利券
            if (CallBase::FROM_DAILY_FREE == $log->from) {
                $freeCallRecord = UserFreeCall::checkValid($userId);
                $freeCallRecord && $freeCallRecord->update([
                    'used_at' => time(),
                    'call_id' => $log->id,
                    'call_type' => $log->call_type,
                    'status' => UserFreeCall::STATUS_USED
                ]);
            }
        }
        return $log->save() ? true : false;
    }

    /**
     * 回调处理-离开频道（挂断）
     */
    static function callbackChannelOut($userId = 0, $chatUserId = 0, $channelId = '', $reasonCode = 1)
    {
        if ($userId == $chatUserId || !$userId || !$chatUserId || !$channelId) return false;
        $log = self::checkRecord($userId, $chatUserId);
        if (!$log) return false;
        if ($log->channel_id != $channelId) {
            log_info(__CLASS__ . "==callbackChannelOut==Log:{$log->id}=={$log->channel_id}=={$channelId}");
            return false;
        }
        //挂断状态修改
        $log = self::channelOutUpdate($log, $reasonCode);
        return $log;
    }

    /**
     * 更新通话时间
     */
    static function updateCallTime($log = null, $userId = 0)
    {
        $log->call_time = time() - $log->answer_time;
        $heartbeatField = $userId == $log->user_id ? 'heartbeat_user' : 'heartbeat_chat';
        $log->{$heartbeatField} = time();
        $log->saveOrFail();
        return $log;
    }

    /**
     * 当前正在通话的记录（排除新手福利语聊记录）
     */
    static function getChatting()
    {
        $where = [
            ['status', self::STATUS_ING],
            ['answer_time', '>', 0],
            ['from', '<>', self::FROM_NEW],
//            ['from', '<>', self::FROM_DAILY_FREE],
            ['from', '<>', self::FROM_IOS_QUICK_MATCH],
//            ['from', '<>', self::FROM_INVITE_CALL]
        ];
        return self::where($where)->get()->toArray();
    }

    /**
     * 通话结束状态修改
     */
    static function channelOutUpdate($log = null, $reasonCode = 1, $agoraStatus = 0, $isYellowHangup = 0)
    {
        //已经挂断
        // if ($log->end_time) return false;
        $status = $reasonCode == 1 ? self::STATUS_OK : self::STATUS_ERR_HANGUP;
        $log->status = $status;
        //兼容异常接听时间
        if (!$log->answer_time) {
            $log->answer_time = time();
        }
        //结束时间
        if (!$log->end_time) {
            $ts = time();
            $log->call_time = $ts - $log->answer_time;
            $log->end_time = $ts;
            $log->agora_hangup_status = $agoraStatus;

            if ($isYellowHangup) {
                $log->status = self::STATUS_YELLOW_HANGUP;
            }

            // 统计特惠视频通话时长
            if ($log->from == self::FROM_DISCOUNT_CALL) {
                DiscountVideoRank::updateCallTime($log->chat_user_id, $log->call_time);
            }
        }
        $result = $log->saveOrFail();
        return $log;
    }

    /**
     * 构建列表元素
     */
    static function buildItem($item = null, $userProfile = [], $avatarSize = 200)
    {
        if (!$userProfile) return [];
        return [
            'user_id' => $item['chat_user_id'],
            'avatar' => UserProfile::buildAvatar($userProfile['avatar'], $avatarSize),
            'coin_setting' => $userProfile['coin_setting'],
            'nick_name' => $userProfile['nick_name'],
            'gender' => $userProfile['gender'],
            'age' => DateUtil::dateDiff($userProfile['birthday'], date('Y-m-d'), 'Y'),
            'call_time' => date('Y-m-d H:i', $item['start_time']),
            'call_status' => self::getCallStatus($item['is_caller'], $item['duration']),
            'button_text' => '重新拨打',
            'button_status' => 1, //1-可拨打，0-不可拨打
            //声网频道ID
            'channel_id' => $item['channel_id'],
            //话单状态：1-通话结束，0-未接通以及其他
            'status' => in_array($item['status'], self::DONE_STATUS) ? 1 : 0,
            'call_id' => $item['call_id'],
            //通话类型
            'call_type' => $item['call_type'],
            //话单来源说明
            'call_from' => self::getCallTitle($item['from'], $item['call_mark']),
        ];
    }

    /**
     * 获取通话类型
     */
    static function getCallTitle($callFrom = 0, $callMark = 1)
    {
        switch ($callFrom) {
            case self::FROM_INVITE_CALL:
                return '视频约会';
            case self::FROM_QUICK_MESSAGE:
                return '随心聊';
            case self::FROM_DAILY_FREE:
                return $callMark == 2 ? '速配' : '天天福利';
            case self::FROM_DISCOUNT_CALL:
                return '特惠视频';
        }
        return '常规';
    }

    /**
     * 获取通话记录状态
     */
    static function getCallStatus($isCaller = 0, $callDuration = 0)
    {
        if (!$callDuration) return '未接通';
        $minutes = ceil($callDuration / 60);
        return ($isCaller ? '拨出' : '接听') . "{$minutes}分钟";
    }

    /**
     * 分解参数
     */
    static function getParams($callbackArray)
    {
        $channelId = $callbackArray['payload']['channelName'];
        $channel = explode('|', $channelId);
        return [
            'eventType' => $callbackArray['eventType'],
            'userId' => $channel[0],
            'chatUserId' => $channel[1],
            'channelId' => $channelId,
            'reasonCode' => $callbackArray['payload']['reason'] ?? 1,
            //通话类型：1-视频，0-语音
            'callType' => isset($channel[3]) && $channel[3] == '1' ? VideoCall::CALL_TYPE : VoiceCall::CALL_TYPE,
            //事件用户ID
            'eventUid' => $callbackArray['payload']['uid'] ?? 0,
        ];
    }

    /**
     * 截止当前语聊总花费
     */
    static function calTotalCost($record = [], $coinSetting = 0)
    {
        if (!$record || !$coinSetting) return 0;

        if ($record['from'] == self::FROM_INVITE_CALL) {
            $second = self::calTotalMinutes($record) - InviteVideoCode::FREE_TIME;
            if ($second <= 0) {
                return 0;
            }

            return $second * $coinSetting;
        }
        return self::calTotalMinutes($record) * $coinSetting;
    }

    /**
     * 截止当前语聊总时间（分钟）
     */
    static function calTotalMinutes($record = [])
    {
        return ceil((time() - $record['answer_time']) / 60);
    }

    /**
     * 计算已完成话单接听电话时长
     */
    static function sumTotalCallTime($userId = 0, $call = true, $startTime = '', $type = 'sec')
    {
        $where = [
            ['status', self::STATUS_OK],
            ['call_time', '>', 0],
        ];
        if (!$call) $where[] = ['chat_user_id', $userId];
        else $where[] = ['user_id', $userId];

        if ($startTime) $where[] = ['start_time', '>=', strtotime($startTime)];
        //计算总秒数
        if ('sec' == $type) {
            $data = self::where($where)->select(Db::raw('SUM(call_time) as total_time'))->get();
            return $data[0]->total_time ?: 0;
        } else {
            //话单分钟数
            $items = self::where($where)->pluck('call_time')->toArray();
            $minutes = 0;
            foreach ($items as $calltime) $minutes += self::getCallMinutes($calltime);
            return $minutes;
        }
    }

    /**
     * 未接听和正在通话中的声优
     */
    static function getCallingHostIds()
    {
        $status = [self::STATUS_ING, self::STATUS_NO_PICK];
        return self::whereIn('status', $status)->pluck('chat_user_id')->toArray();
    }

    /**
     * 呼叫中和正在通话中的用户
     */
    static function getCallingUsers()
    {
        $status = [self::STATUS_ING, self::STATUS_NO_PICK];
        $data = array_merge(
            VoiceCall::whereIn('status', $status)->select(['chat_user_id', 'user_id'])->get()->toArray(),
            VideoCall::whereIn('status', $status)->select(['chat_user_id', 'user_id'])->get()->toArray()
        );
        return array_unique(array_merge(array_column($data, 'user_id'), array_column($data, 'chat_user_id')));
    }

    /**
     * 用户是否正在通话中
     */
    static function checkUserChatting($userId = 0, $includeCalling = false)
    {
	    $record = self::checkLastRecord($userId);
	   # return $record;
        $checkStatus = $includeCalling ? [self::STATUS_ING, self::STATUS_NO_PICK] : [self::STATUS_ING];
        return $record && in_array($record->status, $checkStatus) ? 1 : 0;
    }

    /**
     * 根据用户获取流水
     */
    static function getTotalByUsers($userIds = [], $startTime = '', $endTime = '')
    {
        $where = [
            ['total_cost', '>', 0]
        ];
        $validStatus = [self::STATUS_OK, self::STATUS_ERR_HANGUP];
        if ($startTime) $where[] = ['created_at', '>=', $startTime];
        if ($endTime) $where[] = ['created_at', '<', $endTime];
        $data = self::where($where)
            ->whereIn('chat_user_id', $userIds)
            ->whereIn('status', $validStatus)
            ->select(Db::raw('SUM(total_cost) as total_cost'))->first();
        return $data && $data->total_cost ? $data->total_cost : 0;
    }

    /**
     * 查找记录-新手福利语聊
     */
    static function checkRecordForNew($userId = 0)
    {
        $where = [
            'user_id' => $userId,
            'from' => self::FROM_NEW
        ];
        return self::where($where)->orderBy('id', 'desc')->first();
    }

    /**
     * 当前新手福利通话记录
     */
    static function getCallsForNew($status = self::STATUS_NO_PICK)
    {
        $where = [
            ['status', $status],
            ['from', '=', self::FROM_NEW]
        ];
        if (self::STATUS_ING == $status) {
            $where[] = ['answer_time', '>', 0];
        } elseif (self::STATUS_NO_PICK == $status) {
            $where[] = ['answer_time', 0];
        }
        return self::where($where)->get()->toArray();
    }

    /**
     * 当前天天免费福利通话记录
     */
    static function getCallsForDailyFree($status = self::STATUS_NO_PICK)
    {
        $where = [
            ['status', $status],
            ['from', self::FROM_DAILY_FREE]
        ];
        if (self::STATUS_ING == $status) {
            $where[] = ['answer_time', '>', 0];
        } elseif (self::STATUS_NO_PICK == $status) {
            $where[] = ['answer_time', 0];
        }
        return self::where($where)->get()->toArray();
    }

    /**
     * 当前一键语聊正在拨叫的用户
     */
    static function getQuickCalling()
    {
        //IOS快速匹配
        $where = [
            ['status', self::STATUS_NO_PICK],
            ['answer_time', '=', 0],
            ['from', '=', self::FROM_IOS_QUICK_MATCH]
        ];
        //新版随心聊
        $orWhere = [
            ['status', self::STATUS_NO_PICK],
            ['answer_time', '=', 0],
            ['from', '=', self::FROM_QUICK_MESSAGE]
        ];
        return self::where($where)->orWhere(function ($query) use ($orWhere) {
            $query->where($orWhere);
        })->get()->toArray();
    }

    /**
     * 获取话单的单价
     */
    static function getCallCoinSetting($callRecord = 0, $callType = 0)
    {
        switch ($callRecord['from']) {
            //随心聊
            case self::FROM_QUICK_MESSAGE:
//                return $callType == VoiceCall::CALL_TYPE ?
//                    ConfigUtil::getQuickCallCoin('voice') :
//                    ConfigUtil::getQuickCallCoin('video');
            //视频邀约
            case self::FROM_INVITE_CALL:
//                return InviteVideoCode::PLATFORM_SUBSIDY_PRICE;
            // return $callType == VoiceCall::CALL_TYPE ?
            //     ConfigUtil::getFreeCallCoin('voice') :
            //     ConfigUtil::getFreeCallCoin('video');
            //天天福利
            case self::FROM_DAILY_FREE:
            case self::FROM_DISCOUNT_CALL:
            default:
                return $callRecord['coin_setting'];
        }
        return 100;
    }

    /**
     * 计算话单通话分钟数
     */
    static function getCallMinutes($callSecs = 0)
    {
        return !$callSecs || $callSecs < 1 ? 0 : ceil($callSecs / 60);
    }

    /**
     * 根据订单号区分视频，语音（特殊）
     */
    static function pickCallTypeFromOrder($orderIds = [])
    {
        if (empty($orderIds)) return;
        $arr1 = Db::table('voice_call')->whereIn('order_id', $orderIds)->pluck('call_type', 'order_id')->toArray();
        return array_merge($arr1, Db::table('video_call')->whereIn('order_id', $orderIds)->pluck('call_type', 'order_id')->toArray());
    }

    /**
     * 最近被主播呼叫天天福利记录
     */
    static function checkFreeCallFromHost($userId = 0, $validMinutes = 120)
    {
        $where = [
            ['chat_user_id', $userId],
            ['call_mark', 2],
        ];
        //时间范围
        $validMinutes > 0 && $where[] = ['created_at', '>', date('Y-m-d H:i:s', time() - $validMinutes * 60)];
        //语音记录
        $voiceRecord = VoiceCall::where($where)->whereIn('status', self::DONE_STATUS)->orderBy('id', 'desc')->first();
        //视频记录
        $videoRecord = VideoCall::where($where)->whereIn('status', self::DONE_STATUS)->orderBy('id', 'desc')->first();
        if (!$voiceRecord && !$videoRecord) return null;
        elseif (!$voiceRecord) return $videoRecord;
        elseif (!$videoRecord) return $voiceRecord;
        else return (string)$voiceRecord->created_at > (string)$videoRecord->created_at ? $voiceRecord : $videoRecord;
    }

    /**
     * 最近被主播呼叫天天福利超过次数的
     */
    static function getCalledByTimes($lmtTimes = 3, $offDate = '')
    {
        $where = [
            ['call_mark', 2],
        ];
        $offDate && $where[] = ['created_at', '>', (string)$offDate];
        $userIds = array_merge(
            VoiceCall::whereIn('status', CallBase::DONE_STATUS)->where($where)->pluck('chat_user_id')->toArray(),
            VideoCall::whereIn('status', CallBase::DONE_STATUS)->where($where)->pluck('chat_user_id')->toArray()
        );
        $callInfo = array_count_values($userIds);
        $countInfo = array_filter($callInfo, function ($v) use ($lmtTimes) {
            return $v >= $lmtTimes;
        });
        return !$countInfo ? [] : array_keys($countInfo);
    }


    /**
     * 最近被主播呼叫天天福利超过次数的
     */
    static function getCalledRefuse($user_id = 0,$lmtTimes = 1, $offDate = '')
    {
        $where = [
            ['call_mark', 2],
            ['user_id',$user_id]
        ];
        $offDate && $where[] = ['created_at', '>', (string)$offDate];
        $userIds = array_merge(
            VoiceCall::whereIn('status', CallBase::DONE_STATUS)->where($where)->pluck('chat_user_id')->toArray(),
            VideoCall::whereIn('status', CallBase::DONE_STATUS)->where($where)->pluck('chat_user_id')->toArray()
        );
        $callInfo = array_count_values($userIds);
        $countInfo = array_filter($callInfo, function ($v) use ($lmtTimes) {
            return $v >= $lmtTimes;
        });
        return !$countInfo ? [] : array_keys($countInfo);
    }


    /**
     * 主播呼叫天天福利数量
     */
    static function getHostFreeCallNum($userId = 0, $startTime = '', $callType = -1)
    {
        $where = [
            ['user_id', $userId],
            ['from', self::FROM_DAILY_FREE],
            ['call_mark', 2],
        ];
        $startTime && $where[] = ['created_at', '>', $startTime];
        switch ($callType) {
            case VoiceCall::CALL_TYPE:
                return VideoCall::where($where)->whereIn('status', self::DONE_STATUS)->count();
            case VideoCall::CALL_TYPE:
                return VideoCall::where($where)->whereIn('status', self::DONE_STATUS)->count();
        }
        return VoiceCall::where($where)->whereIn('status', self::DONE_STATUS)->count() +
            VideoCall::where($where)->whereIn('status', self::DONE_STATUS)->count();
    }

    /********统计相关********/
    /**
     * 获取通话单总数
     */
    static function getCallNum(
        $type = 'success_num',
        $start = '',
        $end = '',
        $from = 0,
        $userId = 0,
        $chatUserId = 0,
        $channel = ''
    ) {
        $where = [];
        $callType = ['total_call_minutes','total_call_time'];
        if(in_array($type,$callType)){
            $start && $where[] = ['end_time', '>=', strtotime($start)];
            $end && $where[] = ['end_time', '<',  strtotime($end)];
        }else{
            $start && $where[] = ['created_at', '>=', $start];
            $end && $where[] = ['created_at', '<', $end];
        }


        $userId && $where[] = ['user_id', $userId];
        $chatUserId && $where[] = ['chat_user_id', $chatUserId];

        if ($from == self::FROM_DAILY_FREE_HOST) {
            $where[] = ['call_mark', 2];
            $where[] = ['from', self::FROM_DAILY_FREE];
        } elseif ($from == self::FROM_DAILY_FREE) {
            $where[] = ['call_mark', 1];
            $where[] = ['from', self::FROM_DAILY_FREE];
        } elseif ($from) {
            $where[] = ['from', $from];
        }
        switch ($type) {
            //成功总话单
            case 'success_num':
                $where[] = ['call_time', '>', 0];
                $query = self::buildQueryByChannel($channel, $where, self::DONE_STATUS);
                return $query->count();

            //成功呼叫人数
            case 'success_caller_num':
                $where[] = ['call_time', '>', 0];
                $query = self::buildQueryByChannel($channel, $where, self::DONE_STATUS);
                $data = $query->select(Db::raw('count(distinct user_id) as ctn'))->first();
                return $data && $data->ctn ? $data->ctn : 0;

            //成功接听人数
            case 'success_receiver_num':
                $where[] = ['call_time', '>', 0];
                $query = self::buildQueryByChannel($channel, $where, self::DONE_STATUS);
                $data = $query->select(Db::raw('count(distinct chat_user_id) as ctn'))->first();
                return $data && $data->ctn ? $data->ctn : 0;

            //总呼叫人数
            case 'caller_num':
                $query = self::buildQueryByChannel($channel, $where, self::DONE_STATUS);
                $data = $query->select(Db::raw('count(distinct user_id) as ctn'))->first();
                return $data && $data->ctn ? $data->ctn : 0;

            //总被叫人数
            case 'receiver_num':
                $data = self::where($where)->select(Db::raw('count(distinct chat_user_id) as ctn'))->first();
                return $data && $data->ctn ? $data->ctn : 0;

            //接通总时长
            case 'total_call_time':
                $where[] = ['call_time', '>', 0];
                $data = self::where($where)->whereIn('status', self::DONE_STATUS)->select(Db::raw('sum(call_time) as ctn'))->first();
                return $data && $data->ctn ? $data->ctn : 0;

            //失败话单
            case 'call_num_fail':
                $where[] = ['call_time', 0];
                return self::where($where)->whereIn('status', self::FAIL_STATUS)->count();

            //无人接听-失效
            case 'call_num_noanswer':
                $where[] = ['status', self::STATUS_INVALID];
                return self::where($where)->count();

            //主叫挂断
            case 'call_num_hangup':
                $where[] = ['status', self::STATUS_CALLER_STOP];
                return self::where($where)->count();

            //被叫拒绝
            case 'call_num_reject':
                $where[] = ['status', self::STATUS_HOST_REJECT];
                return self::where($where)->count();

            //异常挂断
            case 'call_num_err':
                return self::where($where)->whereIn('status', self::ERR_STATUS)->count();

            //接通总分钟数
            case 'total_call_minutes':
                $where[] = ['call_time', '>', 0];
                $data = self::where($where)->whereIn('status', self::DONE_STATUS)->select(['call_time'])->get()->toArray();
                $minutes = 0;
                foreach ($data as $item) {
                    $item['call_time'] > 10 && $minutes += ceil($item['call_time'] / 60);
                }
                return $minutes;
        }
        return self::where($where)->count();
    }

    /**
     * 渠道统计构建query
     */
    static function buildQueryByChannel($channel = '', $where = [], $validStatus = [])
    {
        $table = self::CALL_TYPE == VideoCall::class ? 'video_call' : 'voice_call';
        //指定渠道
        if (!$channel) {
            $query = self::where($where)->whereIn('status', $validStatus);
        } else {
            $query = Db::table($table)->join('user', function ($join) use ($where, $channel, $table) {
                $where[] = ['user.channel', $channel];
                $join->on('user.id', '=', $table . '.user_id')->where($where);
            })->whereIn($table . 'status', $validStatus);
        }
        return $query;
    }

    /**
     * 根据话单类型返回话单类
     */
    static function getCallClass($callType = 1)
    {
        return $callType == VideoCall::CALL_TYPE ? VideoCall::class : VoiceCall::class;
    }

    /**
     * 漏接电话
     */
    static function getLeakList($userId = 0, $limit = 1)
    {
        $where = [
            ['chat_user_id', $userId],
            // ['from', self::STATUS_CALLER_STOP]
        ];
        $validStatus = [self::STATUS_CALLER_STOP, self::STATUS_NO_PICK];
        $invalidFrom = [self::FROM_DAILY_FREE_HOST, self::FROM_QUICK_MESSAGE, self::FROM_DAILY_FREE];
        $list = self::where($where)->whereIn('status', $validStatus)->whereNotIn('from', $invalidFrom)->orderBy('id', 'desc')->limit($limit)->get()->toArray();
        if ($list) {
            $ids = array_column($list, 'id');
            self::whereIn('id', $ids)->limit($limit)->update(['read' => 1]);
        }
        return $list;
    }

    /**
     * 当前视频邀约通话记录
     * @param int $status
     * @return array
     */
    public static function getCallsForInviteVideo(int $status = self::STATUS_NO_PICK): array
    {
        $where = [
            ['status', $status],
            ['from', self::FROM_INVITE_CALL]
        ];
        if (self::STATUS_ING == $status) {
            $where[] = ['answer_time', '>', 0];
        } elseif (self::STATUS_NO_PICK == $status) {
            $where[] = ['answer_time', 0];
        }
        return self::where($where)->get()->toArray();
    }

    public static function getInfoByChannelId($channelId)
    {
        return  self::where('channel_id',$channelId)->first();
    }
}
